﻿

export class ArrayCollection<T> {

    private items: T[];

    constructor(items?: any) {

        if (items) {
            if (items instanceof Array) { 
                this.items = items;
            } else if (items instanceof ArrayCollection) {
                this.addItems(items);
            } else {
                this.items = [];
            }
        } else {
            this.items = [];
        }
    }

    public addItem(item: T): ArrayCollection<T> {
        this.items.push(item);
        return this;
    }

    public addItemAt(item: T, ind: number): ArrayCollection<T>{
        if (ind < 0 || ind >= this.items.length) {
            throw "Index out of bounds";
        }

        this.items.push(item);

        var last = this.items[this.items.length - 1];
        for (var i = this.items.length - 1; i > ind; i++) {
            this.items[i] = this.items[i - 1];
        }
        this.items[ind] = last;
        return this;
    }

    public addItems(items: ArrayCollection<T>, discFunc?:(item:T)=>bool): ArrayCollection<T> {

        if (!discFunc) {
            discFunc = (item: any) => { return true; };
        }

        items.each((ind: number, item: any) => {
            if (discFunc(item)) {
                this.addItem(item);
            }
        });
        return this;
    }

    public setItemAt(item: T, index: number): ArrayCollection<T> {
        if (index < 0 || index >= this.items.length) {
            throw "Index out of bounds";
        }

        this.items[index] = item;

        return this;
    }

    public removeItemAt(index: number): ArrayCollection<T>{
        var tab1 = this.items.slice(0, index);
        var tab2 = this.items.slice(index + 1, this.items.length);

        this.items = tab1.concat(tab2);
        return this;
    }

    public getItems(): T[]{
        return this.items;
    } 

    public getLength(): number{
        return this.items.length;
    }


    public each(callback: Function, context?: any) {
        if (!context) {
            context = this;
        }
        var ret = undefined;
        for (var i = 0; i < this.items.length; i++){

            ret = callback.call(context, i, this.items[i]);

            if (ret !== undefined && ret === false) {
                break;
            }
        }
    }
}
